package com.glp.work.flow.service.impl;

import com.alibaba.fastjson.JSON;
import com.glp.utils.notify.dto.SendEmail;
import com.glp.work.flow.config.mq.ExchangeQueueConfig;
import com.glp.work.flow.constant.Constants;
import com.glp.work.flow.constant.OrderOperation;
import com.glp.work.flow.constant.OrderStatus;
import com.glp.work.flow.dto.AppInfoResp;
import com.glp.work.flow.dto.EmailDTO;
import com.glp.work.flow.dto.UserDTO;
import com.glp.work.flow.mapper.WfPlatformDefMapper;
import com.glp.work.flow.mapper.WfPlatformDefModleMapper;
import com.glp.work.flow.mapper.WfTaskAssignMapper;
import com.glp.work.flow.pojo.*;
import com.glp.work.flow.request.ProcessStatusRequest;
import com.glp.work.flow.request.TaskAssignInfoDTO;
import com.glp.work.flow.request.WfOrderDetailQueryDTO;
import com.glp.work.flow.service.*;
import com.glp.work.flow.utils.DateUtils;
import com.glp.work.flow.workflow.plugin.flowable.constant.FlowConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Model;
import org.flowable.task.api.Task;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 工单状态以及流程状态同步
 *
 * @author pengjia
 * @version 2020年3月9日 下午6:13:31
 */
@Service
@Slf4j
public class SyncProcessStatusServiceImpl implements SyncProcessStatusService {
    @Value("${glp.fbs-app.appId}")
    private String apploAppId;
    @Autowired
    private WfPlatformDefMapper wfPlatformDefMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Resource
    private WfPlatformDefModleMapper platformDefModleMapper;
    @Resource
    private WfTaskAssignMapper wfTaskAssignMapper;
    @Resource
    private WfTaskSubscriptionRoleService roleService;
    @Resource
    private WfTaskSubscriptionUsersService usersService;
    @Resource
    RepositoryService repositoryService;
    @Resource
    private UserServiceImpl userService;
    @Resource
    private WfEmailLogService wfEmailLogService;
    @Autowired
    TaskService taskService;
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void syncProcessStatus(String appId, ProcessStatusRequest request) {
        WfPlatformDef wfPlatformDef = null;
        {
            log.info("【同步系统信息】获取平台信息！appId：{}，processId：{}", appId, request.getProcessId());
            Example example2 = new Example(WfPlatformDef.class);
            example2.createCriteria().andEqualTo("platformId", appId);
            wfPlatformDef = wfPlatformDefMapper.selectOneByExample(example2);
            WfPlatformDefModle wfPlatformDefModle = new WfPlatformDefModle();
            wfPlatformDefModle.setAppId(wfPlatformDef.getPlatformId());
            wfPlatformDefModle.setModelKey(request.getProcessDefKey());
            try {
                wfPlatformDefModle = platformDefModleMapper.selectOne(wfPlatformDefModle);
                if (wfPlatformDefModle != null && StringUtils.isNotBlank(wfPlatformDefModle.getMqKey())) {
                    wfPlatformDef.setMqKey(wfPlatformDefModle.getMqKey());
                }
            } catch (Exception e) {
                log.error("查询app对应的流程异常！", e);
            }
            request.setUpdateTime(DateUtils.formatDate(DateUtils.getCurrent(), DateUtils.FORMAT_TIME));
        }
        if (StringUtils.isNotBlank(wfPlatformDef.getMqKey())) {
            try {
                String jsonStr = JSON.toJSONString(request);
                log.info("推送消息到业务系统。SYSID：{}，SYSNAME：{}，mqkey:{},MSG：{}", wfPlatformDef.getPlatformId(), wfPlatformDef.getPlatformName(), wfPlatformDef.getMqKey(), jsonStr);
                CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
                rabbitTemplate.convertAndSend(ExchangeQueueConfig.WORK_ORDER_EXCHANGE, wfPlatformDef.getMqKey(), jsonStr, correlationData);
            } catch (Exception e) {
                log.error("推送消息到业务系统异常！", e);
            }
        }
        sendMessages(appId, request);
    }


    @Override
    public void claimSendEmailMq(String userNo, WfOrderDetailQueryDTO wfOrderDetailQueryDTO) {
        log.info("领取任务发送MQ！userNo={}，wfOrderDetailQueryDTO={}", userNo, wfOrderDetailQueryDTO);
        Task task = taskService.createTaskQuery().taskId(wfOrderDetailQueryDTO.getTaskId()).singleResult();
        String processInstanceId = task.getProcessInstanceId();
        ProcessStatusRequest request = new ProcessStatusRequest();
        WfOrder order = orderInfoService.queryWfOrderByPorcessId(processInstanceId);
        request.setProcessDefKey(order.getProcDefKey());
        request.setTaskId(task.getId());
        request.setProcessId(processInstanceId);
        request.setCurrentNode(task.getName());
        request.setUserNo(userNo);
        request.setOrderId(order.getOrderId());
        request.setOperation(FlowConstant.CLAIM);
        request.setProcessDefKey(order.getProcDefKey());
        request.setTaskDefId(task.getTaskDefinitionKey());
        request.setProcessDefId(task.getProcessDefinitionId());
        request.setLogo(FlowConstant.CLAIM);
        request.setSubmitUser(order.getCreateUserNo());
        sendMessages(order.getAppId(), request);
    }

    private void sendMessages(String appId, ProcessStatusRequest request) {
        log.info("【发送Email】获取平台信息！appId：{}，processId：{}", appId, request);
        try {
            Example example = new Example(WfPlatformDef.class);
            example.createCriteria().andEqualTo("platformId", appId);
            WfPlatformDef wfPlatformDef = wfPlatformDefMapper.selectOneByExample(example);
            if (request.getTaskDefId() != null) {
                log.info("应用消息通知是否打开！wfPlatformDefModle：{}", wfPlatformDef.getNotification());
                if (Constants.STATUS_1.equals(wfPlatformDef.getNotification())) {
                    log.info("应用配置信息：{}", wfPlatformDef);
                    WfTaskAssign wfTaskAssign = new WfTaskAssign();
                    wfTaskAssign.setTaskDefId(request.getTaskDefId());
                    wfTaskAssign.setProcDefId(request.getProcessDefId());
                    WfTaskAssign wfTaskAssign1 = wfTaskAssignMapper.selectOne(wfTaskAssign);
                    if (wfTaskAssign1 != null) {
                        log.info("当前节点流程配置信息：{}", wfTaskAssign1);
                        WfEmailLog wfEmailLog = new WfEmailLog();
                        wfEmailLog.setAppId(appId);
                        wfEmailLog.setOperating(request.getOperation());
                        wfEmailLog.setProcessId(request.getProcessId());
                        wfEmailLog.setCurrentInstance(request.getTaskDefId());
                        wfEmailLog.setCreateTime(DateUtils.getCurrent());
                        String dear = "亲爱的用户，您好！<br>";
                        String emailTitle = "工单订阅提醒：【" + wfPlatformDef.getPlatformName() + "】";
                        String emaiOrderId = "&emsp;工单编号：" + request.getOrderId() + "，当前节点：" + request.getCurrentNode();
                        log.info("地址跳转类型：{}", wfPlatformDef.getUrlType());
                        String emailUrl;
                        if (Constants.STATUS_2.equals(wfPlatformDef.getUrlType())) {
                            emailUrl = "&emsp;请点击链接处查看：<a href=" + wfPlatformDef.getUrl() + " target='_blan'>" + wfPlatformDef.getUrl() + "</a><br>";
                        } else {
                            if (Constants.STATUS_0.equals(wfPlatformDef.getUrlType())) {
                                Object o = redisTemplate.opsForValue().get(apploAppId);
                                if (o != null) {
                                    wfPlatformDef.setUrl(o.toString());
                                } else {
                                    AppInfoResp appInfoResp = userService.detailByAppId(apploAppId);
                                    wfPlatformDef.setPlatformName(appInfoResp.getAppName());
                                    wfPlatformDef.setUrl(appInfoResp.getAppUrl());
                                }
                            } else if (Constants.STATUS_1.equals(wfPlatformDef.getUrlType())) {
                                Object o = redisTemplate.opsForValue().get(wfPlatformDef.getPlatformId());
                                if (o != null) {
                                    wfPlatformDef.setUrl(o.toString());
                                } else {
                                    AppInfoResp appInfoResp = userService.detailByAppId(appId);
                                    wfPlatformDef.setPlatformName(appInfoResp.getAppName());
                                    wfPlatformDef.setUrl(appInfoResp.getAppUrl());
                                }
                            }
                            redisTemplate.opsForValue().set(wfPlatformDef.getPlatformId(), wfPlatformDef.getUrl(), 3, TimeUnit.HOURS);
                            String nat = "native://:";
                            if (wfPlatformDef.getUrl() != null && wfPlatformDef.getUrl().startsWith(nat)) {
                                wfPlatformDef.setUrl(wfPlatformDef.getUrl().substring(nat.length()));
                            }
                            emailUrl = "&emsp;请点击链接处查看：<a href=" + wfPlatformDef.getUrl() + " target='_blan'>" + wfPlatformDef.getPlatformName() + "</a><br>";
                        }
                        List<Model> list = repositoryService.createModelQuery().modelKey(request.getProcessDefKey()).orderByCreateTime().desc().list();
                        String modeName = null;
                        if (CollectionUtils.isNotEmpty(list)) {
                            Model model = list.get(0);
                            modeName = model.getName();
                        }
                        log.info("待办消息通知是否打开：{}", wfTaskAssign1.getNotification());
                        toDoEmail(wfTaskAssign1, request, wfPlatformDef, modeName, dear, emaiOrderId, emailUrl, wfEmailLog);
                        log.info("订阅通知发送emailMQ：...................");
                        subscription(request, wfTaskAssign1, emailTitle, modeName, dear, wfPlatformDef, emaiOrderId, emailUrl, wfEmailLog);
                    }
                }
            }
        } catch (Exception e) {
            log.error("发送email异常", e);
        }
    }

    private void toDoEmail(WfTaskAssign wfTaskAssign1, ProcessStatusRequest request, WfPlatformDef wfPlatformDef, String modeName, String dear, String emaiOrderId, String emailUrl, WfEmailLog wfEmailLog) {
        if (Constants.STATUS_1.equals(wfTaskAssign1.getNotification())) {
            log.info("节点配置信息：{}", wfTaskAssign1);
            log.info("待办通知发送emailMQ：...................");
            if (Constants.STATUS_1.equals(wfTaskAssign1.getNotification()) && FlowConstant.BEGIN.equals(request.getLogo())) {
                TaskAssignInfoDTO taskAssignInfo = request.getTaskAssignInfo();
                List<String> userNos = taskAssignInfo.getUserNos();
                SendEmail sendEmail = new SendEmail();
                sendEmail.setSubject("工单待办通知：【" + wfPlatformDef.getPlatformName() + "】" + modeName + "有待处理任务");
                sendEmail.setBody(dear +
                        "&emsp;您有一个待处理任务：【" + wfPlatformDef.getPlatformName() + "】" + modeName + "<br>" +
                        emaiOrderId + "<br>" +
                        emailUrl);
                log.info("【待办】Email信息发送到MQ。SYSID：{}，SYSNAME：{}，MSG：{}", wfPlatformDef.getPlatformId(), wfPlatformDef.getPlatformName(), JSON.toJSONString(sendEmail));
                sendEmailMQ(wfEmailLog, sendEmail, userNos);
            }
        }
    }

    private void subscription(ProcessStatusRequest request, WfTaskAssign wfTaskAssign1, String emailTitle, String modeName, String dear, WfPlatformDef wfPlatformDef, String emaiOrderId, String emailUrl, WfEmailLog wfEmailLog) {

        List<String> userList = new ArrayList<>();

        if (Constants.STATUS_1.equals(wfTaskAssign1.getNoticeCreateUserSwitch())) {
            String submitUser = request.getSubmitUser();
            log.info("获取工单发起人:{}", submitUser);
            userList.add(submitUser);
        }
        List<String> userList1 = roleService.getUserList(wfTaskAssign1.getId());
        if (CollectionUtils.isNotEmpty(userList1)) {
            log.info("获取订阅角色下的用户:{}", userList1);
            userList.addAll(userList1);
        }
        List<String> users = usersService.getUserList(wfTaskAssign1.getId());
        if (CollectionUtils.isNotEmpty(users)) {
            log.info("获取订阅下的用户:{}", userList1);
            userList.addAll(users);
        }
        String notificationType = wfTaskAssign1.getNotificationType();
        List<String> strings = null;
        if (notificationType != null) {
            String[] split = notificationType.split(",");
            strings = Arrays.asList(split);
        }
        HashSet set = new HashSet(userList);
        userList.clear();
        // 将去重后的元素重新添加到list中
        userList.addAll(set);
        log.info("订阅通知收件人：{}", userList);
        SendEmail sendEmail = new SendEmail();
        String userName = null;

        if (request.getUserNo() != null) {
            UserDTO data = userService.getPersonInfo(request.getUserNo()).getData();
            userName = data.getName();
        }
        if (CollectionUtils.isNotEmpty(strings)) {
            if (strings.contains(OrderStatus.PROCESSING.getCode()) && FlowConstant.BEGIN.equals(request.getLogo())) {
                String processor = "处理人：未分配";
                if (request.getCurrentNode().contains(FlowConstant.COUNTERSIGN_NAME)) {
                    processor = "处理人：" + FlowConstant.COUNTERSIGN_NAME;
                }
                sendEmail.setSubject(emailTitle + modeName + "有新进展");
                sendEmail.setBody(dear +
                        "&emsp;您关注的任务有新进展：【" + wfPlatformDef.getPlatformName() + "】" + modeName + "<br>" +
                        emaiOrderId + "，" + processor + "<br>" +
                        emailUrl);
            } else if (strings.contains(OrderStatus.APPROVAL.getCode()) && FlowConstant.CLAIM.equals(request.getLogo())) {
                if (request.getCurrentNode().contains(FlowConstant.COUNTERSIGN_NAME)) {
                    userName = FlowConstant.COUNTERSIGN_NAME + userName;
                }
                sendEmail.setSubject(emailTitle + modeName + "已开始处理");
                sendEmail.setBody(dear +
                        "&emsp;您关注的任务已开始处理：【" + wfPlatformDef.getPlatformName() + "】" + modeName + "<br>" +
                        emaiOrderId + "，处理人：" + userName + "<br>" +
                        emailUrl);
                /*
                 * 邮件发送规则包含驳回，且是END发送MQ，且当前操作为驳回的一种
                 */
            } else if (strings.contains(OrderStatus.REJECT.getCode())
                    && FlowConstant.END.equals(request.getLogo())
                    && (OrderOperation.REJECT_TO_TASK.toString().equals(request.getOperation())
                    || OrderOperation.REJECT_TO_UP.toString().equals(request.getOperation())
                    || OrderStatus.REJECT.toString().equals(request.getOperation()))) {
                sendEmail.setSubject(emailTitle + modeName + "被驳回");
                sendEmail.setBody(dear +
                        "&emsp;您关注的任务被驳回：【" + wfPlatformDef.getPlatformName() + "】" + modeName + "<br>" +
                        emaiOrderId + "，处理人：" + userName + "<br>" +
                        emailUrl);
            } else if (strings.contains(OrderStatus.PASS.getCode())
                    && FlowConstant.END.equals(request.getLogo())
                    && OrderStatus.PASS.toString().equals(request.getOperation())) {
                sendEmail.setSubject(emailTitle + modeName + "审批通过");
                sendEmail.setBody(dear +
                        "&emsp;您关注的任务审批通过：【" + wfPlatformDef.getPlatformName() + "】" + modeName + "<br>" +
                        emaiOrderId + "，处理人：" + userName + "<br>" +
                        emailUrl);
            } else if (strings.contains(OrderStatus.FAIL.getCode())
                    && FlowConstant.END.equals(request.getLogo())
                    && OrderStatus.FAIL.toString().equals(request.getOperation())) {
                sendEmail.setSubject(emailTitle + modeName + "审批拒绝");
                sendEmail.setBody(dear +
                        "&emsp;您关注的任务审批拒绝：【" + wfPlatformDef.getPlatformName() + "】" + modeName + "<br>" +
                        emaiOrderId + "，处理人：" + userName + "<br>" +
                        emailUrl);
            } else {
                return;
            }
            Object o = redisTemplate.opsForValue().get(request.getTaskDefId());
            if (o == null) {
                if (strings.contains(OrderStatus.PROCESSING.getCode()) && FlowConstant.BEGIN.equals(request.getLogo())) {
                    redisTemplate.opsForValue().set(request.getTaskDefId(), request.getProcessId(), 5, TimeUnit.SECONDS);
                }
                log.info("【订阅】Email信息发送到MQ。SYSID：{}，SYSNAME：{}，MSG：{}", wfPlatformDef.getPlatformId(), wfPlatformDef.getPlatformName(), JSON.toJSONString(sendEmail));
                sendEmailMQ(wfEmailLog, sendEmail, userList);
            } else if (!o.toString().equals(request.getProcessId())) {
                log.info("【订阅】Email信息发送到MQ。SYSID：{}，SYSNAME：{}，MSG：{}", wfPlatformDef.getPlatformId(), wfPlatformDef.getPlatformName(), JSON.toJSONString(sendEmail));
                sendEmailMQ(wfEmailLog, sendEmail, userList);
            }
        }
    }

    private void sendEmailMQ(WfEmailLog wfEmailLog, SendEmail sendEmail, List<String> userNoList) {
        if (wfEmailLog != null) {
            if (wfEmailLog.getId() != null) {
                wfEmailLog.setId(wfEmailLog.getId() + 1);
            }
            wfEmailLogService.insertWfEmailLog(wfEmailLog);
            EmailDTO emailDTO = new EmailDTO();
            emailDTO.setSendEmail(sendEmail);
            emailDTO.setId(wfEmailLog.getId());
            emailDTO.setUserNoList(userNoList);
            String jsonStr = JSON.toJSONString(emailDTO);
            log.info("Email发送内容：{}", jsonStr);
            try {
                CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
                rabbitTemplate.convertAndSend(ExchangeQueueConfig.WORK_ORDER_EXCHANGE, ExchangeQueueConfig.WORK_ORDER_EMAIL_KEY, jsonStr, correlationData);
            } catch (Exception e) {
                log.error("Email信息发送到MQ异常！", e);
            }
        }
    }

}
